package com.p2p.front.task;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.p2p.base.model.Money;
import com.p2p.front.async.AsyncBiz;
import com.p2p.front.dal.model.LoanInfo;
import com.p2p.front.dal.model.TenderReturn;
import com.p2p.front.result.TenderReturnResult;
import com.p2p.front.service.ChargeService;
import com.p2p.front.service.LoanInfoService;
import com.p2p.front.service.LoanRepayBizService;
import com.p2p.front.service.LoanRepayService;
import com.p2p.front.service.LoanVariationService;
import com.p2p.front.service.TenderReturnService;
import com.p2p.front.service.TenderService;
import com.p2p.front.service.TransferService;
import com.p2p.front.util.LoanRepayUtil;
import com.p2p.trans.client.facade.AccountQueryFacade;
import com.p2p.trans.client.facade.AccountTransFacade;
import com.p2p.trans.client.result.AccountTransResult;
import com.p2p.user.facade.UserQueryFacade;

/**
 * @author ruiqi
 *
 */
@Service("repayTask")
public class RepayTask extends BaseTask{

	protected final Logger logger = LoggerFactory.getLogger(RepayTask.class);
	
	@Resource
	protected LoanVariationService loanVariationService;
	
	@Resource
	protected LoanInfoService loanInfoService;
	
	@Resource
	protected AccountTransFacade accountTransFacade;
	
	@Resource
	protected AccountQueryFacade accountQueryFacade;
	
	@Resource
	protected UserQueryFacade userQueryFacade;
	
	@Resource
	protected TenderService tenderService;
	
	@Resource
	protected AsyncBiz asyncBiz;
	
	@Resource
	protected LoanRepayBizService loanRepayBizService;
	
	@Resource
	protected LoanRepayService loanRepayService;
	
	@Resource
	protected TenderReturnService tenderReturnService;
	
	@Resource
	private ChargeService chargeService;
	
	@Resource
	private TransferService transferService;
	
	@Scheduled( cron="0 0/3 * * * ? ")   //每10分钟执行一次
	public void flowLoanTenderReturnSchedule(){
		if(!this.doTaskSynchronous(this.getBizKey(), 20)){
			return;
		}
		logger.info("start flowLoanTenderReturn task");
		doBiz();
		logger.info("end flowLoanTenderReturn task");
		this.doRmoveTaskSynchronous(this.getBizKey());
	}
	
	@Transactional(readOnly=false,propagation=Propagation.REQUIRED)
	public void flowLoanTenderReturn(Date date){
		
		List<TenderReturn> list = tenderReturnService.queryByDate(date, 1);
		if(CollectionUtils.isEmpty(list)){
			return;
		}
		Map<String,Money[]> loanRepayMap = new HashMap<String,Money[]>();
		Set<Long> loanIdSet = new TreeSet<Long>();
		Set<Long> tenderIdSet = new TreeSet<Long>();
		Date now = new Date();
		Money allNeedReturnAmount = new Money(0L);
		Map<Long,LoanInfo> loanInfoMap = new HashMap<Long,LoanInfo>();
		for(TenderReturn tenderReturn:list){
			Long loanId = tenderReturn.getLid();
			loanIdSet.add(loanId);
			Long tenderId = tenderReturn.getTid();
			tenderIdSet.add(tenderId);
			Integer no = tenderReturn.getNo();
			String key = loanId+"_"+no;
			if(loanRepayMap.get(key)==null){
				loanRepayMap.put(key, new Money[]{new Money(0,0),new Money(0,0)});
			}
			if(loanInfoMap.get(key)==null){
				LoanInfo loanInfo = loanInfoService.getLoanInfoById(loanId);
				loanInfoMap.put(loanId, loanInfo);
			}
			
			Money returnAmount = LoanRepayUtil.caluReturnAmount(tenderReturn, false, loanInfoMap.get(tenderReturn.getLid()),now);
			allNeedReturnAmount.add(returnAmount);
		}
		//取消相关的债权转让
		transferService.cancelTransferByTid(new ArrayList<Long>(tenderIdSet));
		
		AccountTransResult tender2MiddleResult = loanRepayBizService.tender2MiddleTrans(allNeedReturnAmount,"自动还款打款");
		
		if(!tender2MiddleResult.isSuccess()){
			logger.error("tender2MiddleTrans error, code="+tender2MiddleResult.getResultCode());
			return;
		}
		
		for(TenderReturn tenderReturn:list){
			Long loanId = tenderReturn.getLid();
			Integer no = tenderReturn.getNo();
			String key = loanId+"_"+no;
			TenderReturnResult returnResult = tenderReturnService.doReturn(tenderReturn, false, loanInfoMap.get(loanId), now);
			//boolean updateResult = tenderReturnService.updateStatusFromReturn(tenderReturn.getId());
			if(returnResult.isSuccess()){
				logger.info("tender return successed tenderReturn id="+tenderReturn.getId());
				Money returnAmount = returnResult.getTenderReturn().getAmount();
				Money returnPrincipal = returnResult.getTenderReturn().getPrincipal();
				loanRepayMap.get(key)[0].add(returnAmount);
				loanRepayMap.get(key)[1].add(returnPrincipal);
				Money interest = new Money(returnAmount.getCent()-returnPrincipal.getCent());
				chargeService.doChargeForInterest(String.valueOf(tenderReturn.getUid()), interest);
			}else{				
				logger.error("tender return status error,returnResult="+returnResult);
			}
			
		}
		
		Money allReturnAmount = new Money(0,0);
		for(Entry<String,Money[]> entry:loanRepayMap.entrySet()){
			String key = entry.getKey();
			Money[] value = entry.getValue();
			String[] array = key.split("_");
			Long loanId = Long.valueOf(array[0]);
			Integer no = Integer.valueOf(array[1]);
			
			//更新还款金额
			loanRepayService.updateForAddRepay(loanId, no, value[0], value[1]);
			
			logger.info("update amount for loanRepay repay="+key +",returnAmount = "+value[0]+",returnPrincipal="+value[1]);
			
			//流转标只要有任何还款就更新为已还款状态，以免在预期还款中被扫描出来
			loanRepayService.updateStatus(loanId,no, 11, 21);
			
			allReturnAmount.add(value[0]);
			
		}
		Money limitAmount = new Money(allNeedReturnAmount.getCent()-allReturnAmount.getCent());
		if(limitAmount.getCent()>0){
			logger.error("auto return limitAmount ="+limitAmount.toString());
			AccountTransResult middle2TenderResult = loanRepayBizService.middle2TenderTrans(limitAmount, "自动还款打款剩余退回");
			if(!middle2TenderResult.isSuccess()){
				logger.error("middle2TenderTrans error");
			}
		}else{
			logger.info("auto return succesed ,allReturnAmount="+allReturnAmount.toString());
		}
		

	}
	/*private boolean doTransForReturn(TenderReturn tenderReturn){
		Tender tender = tenderService.getByTid(tenderReturn.getTid());
		String userAccountNo = tender.getUserAccount();
		TransInfo transInfo = new TransInfo();
		
		transInfo.setTransAccountIn(userAccountNo);
		transInfo.setTransAccountOut(TenderConsts.innerTenderAccountNo);
		transInfo.setTransAmount(tenderReturn.getAmount());
		AccountTransResult transResult = accountTransFacade.transfer(transInfo);
		if(transResult.isSuccess()){
			logger.info("tender return succes return id="+tenderReturn.getId());
			broadcastForTenderReturn(tenderReturn);
			return true;
		}else{
			logger.error("tender return error return id="+tenderReturn.getId());
			return false;
		}
	}*/
	
	/*private boolean doTransForLoanRepay(LoanRepay loanRepay){
		AccountQueryResult result = accountQueryFacade.getAccountByUserId(String.valueOf(loanRepay.getUid()));
		String userAccountNo = null;
		Money balance = null;
		if(result.isSuccess()){
			userAccountNo = result.getAccountVO().getAccountNo();
			balance= result.getAccountVO().getCanUserBalance();
		}else{
			logger.error("account error when doTransForLoanRepay loanRepayId="+loanRepay.getRid());
			return false;
		}
		if(balance.getCent()<loanRepay.getRepayAmount().getCent()){
			logger.error("balance not enough when doTransForLoanRepay loanRepayId="+loanRepay.getRid());
			return false;
		}
		TransInfo transInfo = new TransInfo();
		transInfo.setTransCode(TransCodeEnum.TXCODE_TRANSFER);
		transInfo.setSubTransCode(SubTransCodeEnum.SUB_TRANSFER_TRANSFER);
		transInfo.setTransAccountIn(TenderConsts.innerTenderAccountNo);
		transInfo.setTransAccountOut(userAccountNo);
		transInfo.setTransAmount(loanRepay.getRepayAmount());
		AccountTransResult transResult = accountTransFacade.transfer(transInfo);
		if(transResult.isSuccess()){
			logger.info("loan Repay succes return id="+loanRepay.getRid());
			
			return true;
		}else{
			logger.error("loan Repay error return id="+loanRepay.getRid());
			return false;
		}
	}
	*/
	/*@Transactional(readOnly=false,propagation=Propagation.REQUIRED)
	public void nomalLoanTenderReturn(Long loanRepayId){
		LoanRepay loanRepay = this.loanRepayService.getByRid(loanRepayId);
		if(loanRepay==null||loanRepay.getStatus()!=11){
			return;
		}
		boolean repayUpdateResult = loanRepayService.updateStatus(loanRepayId, 11, 21);
		if(repayUpdateResult==false){
			return;
		}
		if(!doTransForLoanRepay(loanRepay)){
			return;
		}
		Long lid =loanRepay.getLid();
		Integer no = loanRepay.getNo();
		
		List<TenderReturn> list = this.tenderReturnService.queryByLidAndNo(lid, no);
		for(TenderReturn tenderReturn:list){
			boolean returnUpdateResult = tenderReturnService.updateStatusFromReturn(tenderReturn.getId());
			if(returnUpdateResult){
				doTransForReturn(tenderReturn);		
			}else{
				logger.error("tender return status error ，tenderReturn id="+tenderReturn.getId());
			}
		}
	}*/
	
	

	@Override
	public String getBizKey() {
		String bizKey = "task_flowLoanTenderReturnSchedule_";
		return bizKey;
	}

	@Override
	public void doBiz() {
		this.flowLoanTenderReturn(new Date());
	}
}
